#!/usr/bin/env python
from __future__ import unicode_literals
import pdtools
import numpy as S
import json
import time
import jsfits
import sys
import os
import glob
import pdauxtools as AT
from csdb.csdb import csdb
import logreport
from astropy.io import fits
from  version import VERSION
from optparse import OptionParser
#-
#- Purpose:
#- 1. generate products of [QDT,QPO,QF,QUPLIM];
#- 2. sending products to CSC
#- TODO: QTI,QLC
#- 
#-Author: Chao wu <cwu@bao.ac.cn>
#-
T = VERSION()
__version__= T.curversion

def readOTtxt(fil):
     """
     readOT txt file .
     return o:
     o= dict{}
     o['header']= [txt header]
     o['data']= column
     """
     COLS={'0':['DELTAT',S.int0],'1':['EXPTIME',S.float_],'2':['DT',S.string_],
           '3':['FILTER',S.string_],'4':['MAG',S.float_],'5':['MAGERR',S.float_],
           '6':['UPMAG',S.float_],'7':['RA',S.float_],'8': ['DEC',S.float_],
           '9':['XC',S.float_],'10':['YC',S.float_],'11':['DISTANCE',S.float_],
           '12':['IDCAND',S.string_],'13':['BURST_ID',S.string_ ],'14':['TILENUM',S.int0],
           '15':['IMAGEID',S.string_],'16':['TEL',S.string_],'17':['FCHART',S.string_],
           '18':['ALT_ID',S.string_],'19':['TRIG_NAM',S.string_]}
     
     
     ff = open(fil)
     O={}
     O['header']={}
     for f in ff:
         t0=f.strip()
         if len(t0)==0:continue
         if t0[:2] == "#-" or t0[0]!="#" or (not "=" in t0):
             continue
    #     print (t0)
         t0c= t0.replace("#","")
         kk,val= t0c.split("=")
         kk=kk.strip()
         val=val.strip()
     #    print (kk,val)
         if kk in [ "OBS_ID"]:
             val = int(val)
         if kk in ['TRIG_MJD']:
             val = float(val)  
         O['header'][kk] = val

     dd=S.loadtxt(fil,dtype=S.string_)
     O['data']={}
     if len(dd)== 0 :
          O['header'] = 'True'
     #- correct value
     O['header']['FINDING'] = bool(O['header']['FINDING'])
     #print (O['header']['UPMAG'])
     if not  O['header']['UPMAG'] == 'None':
        O['header']['UPMAG'] = S.float_(O['header']['UPMAG'])
     O['header']['RA_C'] = S.float_(O['header']['RA_C'])
     O['header']['DEC_C'] = S.float_(O['header']['DEC_C'])

          
     if len(dd.shape)==1:
          dd=S.array([dd])

     #-- candidate numb
     if O['header']['FINDING']:
         O['header']['CANDNUMB'] = len(dd)
     else:
         O['header']['CANDNUMB'] = 0 
     
     vv={}
     for c0 in range(len(COLS.keys())):
         cn = COLS['%i' %c0]
#         print (cn)
         if cn[0]=='FCHART':
            vv[cn[0]] = [ "http://222.168.154.194:8081/pub/fchart/%s" %fc0.decode('utf-8')  for fc0 in list(S.array(dd[:,c0],dtype=cn[1]))] 
         else:
             if cn[1] == S.int0:
                vv[cn[0]] = list(int(float(t)) for t in S.array(dd[:,c0],dtype=S.string_))
             else:     
                vv[cn[0]] = list(S.array(dd[:,c0],dtype=cn[1]))
     O['data']= vv
     return O

def calParas(Oin,tag_time='utc',sitena='jilin'):
     """
     calculate parameters from O (Oject O from readOTtxt() )
     return object 
     """
     A=Oin['data']
     H=Oin['header']
     ra_c =  H['RA_C']
     dec_c = H['DEC_C']     
     candnumb = H['CANDNUMB']     
     tag_find= H['FINDING']
     filter0 = A['FILTER'][0]

     
     #-
     #-- cal observation information.
     A['OBJ_ELV'] = []
     A['SUN_ELV'] = []
     A['MOON_ELV'] = []
     A['MOON_DIS'] = []
     A['MOON_PH'] = []
     A['DT_MJD'] = []     
     #A['IMAGEID']=[]
     #A['IDCAND']=[]
     A['GWAC_CHAN']=[]
     A['L']=[]
     A['B']=[]     
 
     #- calculate
     #print (A['IMAGEID'])
     for i in range(len(A['DT'])):
          if tag_find:
               ra0= H['RA_C']
               dec0=H['DEC_C']
          else:
               ra0 = A['RA'][i]
               dec0= A['DEC'][i]
          O = pdtools.OBS(radec=[ra0,dec0],tag_format='deg', dtime=A['DT'][i],tformat='isot',tag_time=tag_time,sitena=sitena)
          O._calMoon()
          O._calSun()
          O._calObjElv()
          A['OBJ_ELV'].append(round(O.obj_altaz[0],2))
          A['SUN_ELV'].append(round(O.sun_altaz[0],2))
          A['MOON_ELV'].append(round(O.moon_altaz[0],2))
          A['MOON_DIS'].append(round(O.Objdis2moon.deg,2))
          A['MOON_PH'].append(round(O.moon_illum,2))
          A['DT_MJD'].append(pdtools.date2mjd(A['DT'][i]))
          #A['IMAGEID'].append(d0[:,14][i].split(".fit")[0])
          #A['IDCAND'].append("%s%s" %(filter0,d0[:,12][i]))
          A['GWAC_CHAN'].append("GWAC-%s" %filter0.decode('utf-8'))
          A['L'].append(O.ObjSky.galactic.l.value)
          A['B'].append(O.ObjSky.galactic.b.value)          

     Oin['data'] = A
     return Oin     

def combObjs(Ocs):
     """
     Ocs is list after processing of 'O=readOTtxt(txtfile), Oc=calParas(O)'
     this is prepare for product of QLC input.
     return Ocq
     """
     
     Ocq = dict(Ocs[0])
     kks = Ocq['data'].keys()
     for k in kks :
          Ocq['data'][k]=[]

     if len(Ocs)>1:
          for j,Ocsi in enumerate(Ocs):
              if Ocsi['header']['FINDING'] and len(Ocsi['data']['IDCAND'])>0:
                   if Ocsi['data']['IDCAND'][0]!=b'999':
                     for k in kks:
                        Ocq['data'][k].extend( Ocsi['data'][k])
     return Ocq            
     

def fill2Prod(Odat, cards=['QDT_GWAC','QF_GWAC','QPO_GWAC','QUPLIM_GWAC']):
     """
     Odat: from readOTtxt()
     cards: product name in ['QDT_GFT_CGFT','QF_GFT_CGFT','QPO_GFT_CGFT']
     """
     SOFT_VER = 0.1
     GLDM_VER = 0.1
     TSTART  = 0
     TSTOP   = 1

     #---
     ptime= int(round(time.time()))
     ptimedate= pdtools.epoch2date(ptime)
     ptj  = pdtools.timeObj(ptimedate,tformat='isot')
     ptimemjd = ptj.mjd

     A = Odat['data']
     H = Odat['header']
     #print (A['GFT_CHAN'])
     gwac_chan= A['GWAC_CHAN'][0]
     filter0 = H['FILTER']
     burst_id = H['BURST_ID']
     candnumb = H['CANDNUMB']

     outfils=[]
     for card in cards:
         print ("Info: doing card = %s" %card) 
         #-- 
         prodid= "%s__%s__%s__%s" %(burst_id,card,gwac_chan,ptime)
         #---
         outsurffix="_%s_%s_%s.fits" %(burst_id,filter0,ptime)

         outfits= "%s%s"  %(card,outsurffix)
         tmpoutfits="tmp_%s" %outfits
         pdtools.cptempProd(card,outfits=tmpoutfits)
         print(f'outfits={outfits}')
         
         T=jsfits.PDFits()
         #T.readfits(tmpoutfits,tempdir="./")
         T.readfits(tmpoutfits, tempdir="/home/cgft/software/softgft_mainFocus/")
         
         
         #- fill data FOR HEADER
         T.PDX.HDU1.HEADER.BURST_ID.value=H['BURST_ID']
         T.PDX.HDU1.HEADER.OBS_ID.value=H['OBS_ID']
         T.PDX.HDU1.HEADER.ORIGIN.value=H['ORIGIN']
         T.PDX.HDU1.HEADER.DATE.value=ptimedate
         T.PDX.HDU1.HEADER.DATE_MJD.value=ptimemjd
         T.PDX.HDU1.HEADER.PRODID.value=prodid
         T.PDX.HDU1.HEADER.TRIG_NAM.value=A['TRIG_NAM'][0]
         T.PDX.HDU1.HEADER.ALT_ID.value=A['ALT_ID'][0]
         #---
         T.PDX.HDU1.HEADER.SOFT_VER.value=SOFT_VER
         T.PDX.HDU1.HEADER.GLDM_VER.value=GLDM_VER
         T.PDX.HDU1.HEADER.TSTART.value=TSTART
         T.PDX.HDU1.HEADER.TSTOP.value=TSTOP
         
         #--
         T.PDX.HDU2.HEADER.TRIG_MJD.value=H['TRIG_MJD']
         T.PDX.HDU2.HEADER.CANDNUMB.value=H['CANDNUMB']
    
         if candnumb>0:
              #- have to use list insead of array for table.
              T.PDX.HDU2.TABLE.GWAC_CHAN.value=A['GWAC_CHAN']
              T.PDX.HDU2.TABLE.IMAGEID.value =A['IMAGEID']
              T.PDX.HDU2.TABLE.IDCAND.value  =A['IDCAND']
              T.PDX.HDU2.TABLE.FILTER.value  =A['FILTER']
              if card == 'QDT_GWAC':
                  T.PDX.HDU2.TABLE.DT.value     = A['DT']
                  T.PDX.HDU2.TABLE.DT_MJD.value = A['DT_MJD']
              elif card == 'QPO_GWAC':
                  T.PDX.HDU2.TABLE.RA.value =A['RA']
                  T.PDX.HDU2.TABLE.DEC.value=A['DEC']
                  T.PDX.HDU2.TABLE.L.value  =A['L']
                  T.PDX.HDU2.TABLE.B.value  =A['B']
                  T.PDX.HDU2.TABLE.FCHART.value  =A['FCHART']
                  
                  #- TODO , l,b, fchart , equinox
              elif card == 'QF_GWAC':
                  T.PDX.HDU2.TABLE.MAG.value    =A['MAG']
                  T.PDX.HDU2.TABLE.MAGERR.value =A['MAGERR']
                  T.PDX.HDU2.TABLE.EXPTIME.value= A['EXPTIME']
                  #print (A['EXPTIME'])
                  T.PDX.HDU2.TABLE.SYSTEM.value =['AB' for i in A['MAG'] ]
                  T.PDX.HDU2.TABLE.FILTER.value =[filter0 for i in A['MAG']]

                  #print (T.PDX.HDU2.TABLE.MAG.value,T.PDX.HDU2.TABLE.MAGERR.value,T.PDX.HDU2.TABLE.EXPTIME.value,T.PDX.HDU2.TABLE.SYSTEM.value,T.PDX.HDU2.TABLE.FILTER.value)
                  #return T 
              elif card == 'QUPLIM_GWAC':
                  T.PDX.HDU2.TABLE.EXPTIME.value=A['EXPTIME']
                  T.PDX.HDU2.TABLE.SYSTEM.value=['AB' for i in A['MAGERR'] ]
                  T.PDX.HDU2.TABLE.UPMAG.value =A['UPMAG']
                  T.PDX.HDU2.TABLE.FILTER.value=[filter0 for i in A['MAGERR']]
                  
              #-- update HDU3
              T.PDX.HDU3.TABLE.GWAC_CHAN.value  = A['GWAC_CHAN']
              T.PDX.HDU3.TABLE.OBJ_ELV.value   = A['OBJ_ELV']
              T.PDX.HDU3.TABLE.SUN_ELV.value   = A['SUN_ELV']
              T.PDX.HDU3.TABLE.MOON_ELV.value  = A['MOON_ELV']
              T.PDX.HDU3.TABLE.MOON_DIS.value  = A['MOON_DIS']
              T.PDX.HDU3.TABLE.MOON_PH.value   = A['MOON_PH']
              T.PDX.HDU3.TABLE.IMAGEID.value   = A['IMAGEID']
    
    
         #-- output
         T.writeToFITS(outfits)
         os.system('rm -fr %s' %tmpoutfits)
         outfils.append(outfits)
         print(f'2sd outfits={outfits}')

     return outfils


def fill2ProdQLC(Odat,card = 'QLC_GWAC'):
     """
     Odat: from combObjs()
     card: 'QLC_GFT_CGFT'
     """
     SOFT_VER = 0.1
     GLDM_VER = 0.1
     TSTART  = 0
     TSTOP   = 1

     #---
     ptime= int(round(time.time()))
     ptimedate= pdtools.epoch2date(ptime)
     ptj  = pdtools.timeObj(ptimedate,tformat='isot')
     ptimemjd = ptj.mjd

     A = Odat['data']
     H = Odat['header']
     #print (A['GFT_CHAN'])
     gwac_chan= A['GWAC_CHAN'][0]
     filter0 = H['FILTER']
     burst_id = H['BURST_ID']
     candnumb = H['CANDNUMB']

#     outfils=[]
#     for card in cards:
     print ("Info: doing card = %s" %card) 
     #-- 
     prodid= "%s__%s__%s__%s" %(burst_id,card,gwac_chan,ptime)
     #---
     outsurffix="_%s_%s_%s.fits" %(burst_id,filter0,ptime)

     outfits= "%s%s"  %(card,outsurffix)
     tmpoutfits="tmp_%s" %outfits
     pdtools.cptempProd(card,outfits=tmpoutfits)
     
     T=jsfits.PDFits()
     T.readfits(tmpoutfits,tempdir="./")
     
     
     #- fill data FOR HEADER
     T.PDX.HDU1.HEADER.BURST_ID.value=H['BURST_ID']
     T.PDX.HDU1.HEADER.OBS_ID.value=H['OBS_ID']
     T.PDX.HDU1.HEADER.ORIGIN.value=H['ORIGIN']
     T.PDX.HDU1.HEADER.DATE.value=ptimedate
     T.PDX.HDU1.HEADER.DATE_MJD.value=ptimemjd
     T.PDX.HDU1.HEADER.PRODID.value=prodid
     T.PDX.HDU1.HEADER.TRIG_NAM.value=A['TRIG_NAM'][0]
     T.PDX.HDU1.HEADER.ALT_ID.value=A['ALT_ID'][0]
     #---
     T.PDX.HDU1.HEADER.SOFT_VER.value=SOFT_VER
     T.PDX.HDU1.HEADER.GLDM_VER.value=GLDM_VER
     T.PDX.HDU1.HEADER.TSTART.value=TSTART
     T.PDX.HDU1.HEADER.TSTOP.value=TSTOP

     #- update HDU2...
     #----------------
     T.PDX.HDU2.HEADER.TRIG_MJD.value=H['TRIG_MJD']
     T.PDX.HDU2.HEADER.CANDNUMB.value=H['CANDNUMB']
     #- have to use list insead of array for table.
     T.PDX.HDU2.TABLE.GWAC_CHAN.value=A['GWAC_CHAN']
     T.PDX.HDU2.TABLE.IMAGEID.value =A['IMAGEID']
     T.PDX.HDU2.TABLE.IDCAND.value  =A['IDCAND']
     T.PDX.HDU2.TABLE.FILTER.value  =A['FILTER']
     T.PDX.HDU2.TABLE.DELTAT.value  =A['DELTAT']     
     T.PDX.HDU2.TABLE.DT_MJD.value  =A['DT_MJD']     
     T.PDX.HDU2.TABLE.EXPTIME.value  =A['EXPTIME']
     T.PDX.HDU2.TABLE.MAG.value  =A['MAG']
     T.PDX.HDU2.TABLE.MAGERR.value  =A['MAGERR']
     T.PDX.HDU2.TABLE.SUBIMAGE.value  =A['FCHART']
     T.PDX.HDU2.TABLE.RA.value  =A['RA']
     T.PDX.HDU2.TABLE.DEC.value  =A['DEC']
       
     #-- update HDU3
     T.PDX.HDU3.TABLE.GWAC_CHAN.value  = A['GWAC_CHAN']
     T.PDX.HDU3.TABLE.OBJ_ELV.value   = A['OBJ_ELV']
     T.PDX.HDU3.TABLE.SUN_ELV.value   = A['SUN_ELV']
     T.PDX.HDU3.TABLE.MOON_ELV.value  = A['MOON_ELV']
     T.PDX.HDU3.TABLE.MOON_DIS.value  = A['MOON_DIS']
     T.PDX.HDU3.TABLE.MOON_PH.value   = A['MOON_PH']
     T.PDX.HDU3.TABLE.IMAGEID.value   = A['IMAGEID']
    
     #---   
     T.writeToFITS(outfits)
     os.system('rm -fr %s' %tmpoutfits)

     return outfits




if __name__ == "__main__" :
     usage= "\nexample: txt2Prod.py [txtfile:OT_g_30s_001_forCSC.txt] [--nosend]"
     parser = OptionParser( usage,version = __version__ ) #"test")# __version__ )
     parser.add_option("-c", dest="card", type="string", help="product name, in ['QPO4ALL','QLC','QTI'],default='QPO4ALL'",default='QPO4ALL')
 #    parser.add_option("--overwrite",dest="tag_over", action = 'store_true', help="overwrite in csdb if the import file has same file name. ",default=False)
     parser.add_option("--nosend",dest="tag_nosend", action = 'store_true', help="--nosend= dont send products to CSC, default=sending to csc",default=False)
     parser.add_option("--debug",dest="tag_debug", action = 'store_true', help="--debug:log will print on screen. default=saveTofile",default=False)
     opts, args = parser.parse_args()
     tag_nosend = opts.tag_nosend
     card       = opts.card
     tag_debug  = opts.tag_debug
     
     if not len(args) == 1:
        print ("\nexample: txt2Prod.py [txtfile:OT_g_30s_001_forCSC.txt]")
        print ("#- Purpose:\n 1. generate products of [QDT,QPO,QF,QUPLIM];\n 2. sending products to CSC\nTODO: QTI,QLC\n")  
        sys.exit()

     
     fil = args[0]
     ptime= int(time.time())
     if tag_debug:
          logfile=None
     else:
          logfile= "Log_%s_%s.log" %(fil.split(".")[0],ptime)

     log = AT.Logger(logfile,level='debug', when='W6', interval=4, backCount=10)
     log.logger.info( "=== launch  %s ==============" %(sys.argv[0]))
     log.logger.info("txt2Prod.py version = %s " %__version__)
     log.logger.info("LAUNCH CMD = %s " %" ".join(sys.argv))
     #--                      

     if card == 'QPO4ALL':
        print ("Doing %s" %fil)     
        O  = readOTtxt(fil)
        Oc = calParas(O)
        outfils = fill2Prod(Oc,cards=['QDT_GWAC','QF_GWAC','QPO_GWAC','QUPLIM_GWAC'])
     elif card == 'QLC':
          print ("Doing QLC: %s" %fil)               
          lls= glob.glob(fil)
          lls.sort()
          Ocs = []
          for l0 in lls:
               O  = readOTtxt(l0)
               Oc = calParas(O)
               Ocs.append(Oc)
          print("Info: combine Objs done")     
          Odat = combObjs(Ocs)
          outfils= fill2ProdQLC(Odat,card = 'QLC_GWAC')
          print("Info: Generate Product QLC done")          
     log.logger.info("succeeded in generating %s" %outfils)
     #- send to products to CSC
     if not tag_nosend:
         _csdb = csdb()
         #if card == 'QPO4ALL' and type(outfils)==list:

         #elif card == "QLC":
         if type(outfils) != list:
              outfils=[outfils]

         #-- infomation      
         dir0 = os.getcwd()
         p=fits.open(outfils[0])
         gwacobid = str(p[1].data['gwac_obid'][0])
         trigname= fits.getval(outfils[0],'TRIG_NAM') 
         #print (gftobid)
         logreport.rePdLogfile("%s/%s" %(dir0,logfile),gwacobid,ptype='pdsend',host='192.168.199.130:8080',url_ext=f'/gwac/addEvent.action')
    
         for i,fil0 in enumerate(outfils):
             card_in="_".join(fil0.split("_")[:3])
             log.logger.info('Info: sending2CSC--> %s' %fil0)
             response=_csdb.upload(fil0,card=card_in, path0='/default',version= 1 )
             if response.status_code == 200 :
                  log.logger.info("succeeded in Sending %s to CSC" %fil0)
                  logreport.rePdLogEvent(fil0,response.json(),host='192.168.199.130:8080',url_ext=f'/gwac/addEvent.action')
             else:
                  log.logger.critical("Failed: in Sending %s to CSC" %fil0)
     log.logger.info('====== Done in this run of upload products to CSC =========='        )
           
              
              
